#include "LoginDialog.h"
#include "ui_LoginDialog.h"
#include "httpmanager.h"
#include "tcpmanager.h"

#include <QPainter>
#include <QPainterPath>
#include <QDebug>

LoginDialog::LoginDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::LoginDialog)
{
    ui->setupUi(this);

    ui->forget_label->setState("normal","hover","","selected","selected_hover","");

    initHead();
    initHttpHandlers();

    // 连接注册信号
    connect(ui->reg_btn, &QPushButton::clicked, this, &LoginDialog::switchRegister);
    // 连接忘记密码的按钮，等它发出重置界面的信号
    connect(ui->forget_label, &ClickedLabel::clicked, this, &LoginDialog::slot_forget_pwd);
    // 连接登录回包信号
    connect(HttpManager::getInstance().get(), &HttpManager::signal_login_mod_finish, this, &LoginDialog::slot_login_mod_finish);
    // 连接tcp连接请求的信号和槽函数
    connect(this, &LoginDialog::sig_connect_tcp, TcpManager::getInstance().get(), &TcpManager::slot_tcp_connect);
    // 连接TcpManager发出的连接成功的信号
    connect(TcpManager::getInstance().get(), &TcpManager::sig_con_success, this, &LoginDialog::slot_tcp_con_finish);
    // 连接TcpManager发出的连接成功的信号
    connect(TcpManager::getInstance().get(), &TcpManager::sig_login_failed, this, &LoginDialog::slot_login_failed);

}

LoginDialog::~LoginDialog()
{
    qDebug() << "destruct LoginDialog";
    delete ui;
}

// 初始化头像框
void LoginDialog::initHead()
{
    // 加载图片
    QPixmap originalPixmap(":/res/head_1.jpg");
    // 设置图片自动缩放
    qDebug() << originalPixmap.size() << ui->head_label->size();
    originalPixmap = originalPixmap.scaled(ui->head_label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

    // 创建一个与原始图片大小相同的QPixmap，用于绘制圆角图片
    QPixmap roundPixmap(originalPixmap.size());
    // 设置透明填充
    roundPixmap.fill(Qt::transparent);

    QPainter painter(&roundPixmap);
    painter.setRenderHint(QPainter::Antialiasing); // 设置坑锯齿，使圆角更加平滑
    painter.setRenderHint(QPainter::SmoothPixmapTransform);

    // 设置圆角
    QPainterPath path;
    path.addRoundRect(0, 0, originalPixmap.width(), originalPixmap.height(), 10, 10);

    // 将原始图片绘制到roundPixmap上
    painter.drawPixmap(0, 0, originalPixmap);

    // 显示头像
    ui->head_label->setPixmap(roundPixmap);

}

void LoginDialog::showTip(QString str, bool b_ok)
{
    if (b_ok) {
        ui->err_tip->setProperty("state", "normal");
    } else {
        ui->err_tip->setProperty("state", "err");
    }
    ui->err_tip->setText(str);

    repolish(ui->err_tip);
}

void LoginDialog::addTipErr(TipErr te, QString tips)
{
    m_tip_errs[te] = tips;
    showTip(tips, false);
}

void LoginDialog::delTipErr(TipErr te)
{
    m_tip_errs.remove(te);
    if(m_tip_errs.empty()){
        ui->err_tip->clear();
        return;
    }

    showTip(m_tip_errs.first(), false);
}

bool LoginDialog::enableBtn(bool enabled)
{
    ui->login_btn->setEnabled(enabled);
    ui->reg_btn->setEnabled(enabled);
    return true;
}

bool LoginDialog::checkEmailValid()
{
    auto user_email = ui->email_edit->text();
    if(user_email.isEmpty()){
        qDebug() << "Email empty......";
        addTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱不能为空"));
        return false;
    }

    // 邮箱地址的正则表达式
    QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+)");
    bool match = regex.match(user_email).hasMatch(); // 执行正则表达式匹配
    if(!match){
        // 提示邮箱不正确
        addTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱地址不正确"));
        return false;
    }

    delTipErr(TipErr::TIP_EMAIL_ERR);
    return true;
}

bool LoginDialog::checkUserValid()
{
    auto email = ui->email_edit->text();
    if (email.isEmpty()) {
        qDebug() << "email empty " ;
        addTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱不能为空"));
        return false;
    }
    delTipErr(TipErr::TIP_EMAIL_ERR);

    return true;
}

bool LoginDialog::checkPwdValid()
{
    auto pwd = ui->pass_edit->text();
    if (pwd.length() < 6 || pwd.length() > 15){
        qDebug() << "Pass length invalid......";
        //提示长度不准确
        addTipErr(TipErr::TIP_PWD_ERR, tr("密码长度应为6~15"));
        return false;
    }

    // 创建一个正则表达式对象，按照上述密码要求
    // 这个正则表达式解释：
    // ^[a-zA-Z0-9!@#$%^&*.]{6,15}$ 密码长度至少6，可以是字母、数字和特定的特殊字符
    QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*.]{6,15}$");
    bool match = regExp.match(pwd).hasMatch();
    if (!match){
        //提示字符非法
        addTipErr(TipErr::TIP_PWD_ERR, tr("不能包含非法字符且长度为(6~15)"));
        return false;;
    }

    delTipErr(TipErr::TIP_PWD_ERR);

    return true;
}

void LoginDialog::initHttpHandlers()
{
    // 注册获取登录回包逻辑，与ChatServer建立长连接
    m_handlers.insert(ReqId::ID_LOGIN_USER, [this](QJsonObject jsonObj){
        int error = jsonObj["error"].toInt();
        if (error != ErrorCodes::SUCCESS){
            showTip(tr("参数错误"), false);
            enableBtn(true);
            return;
        }

        auto email = jsonObj["email"].toString();
        // 发送信号通知tcpManager发送长链接
        ServerInfo si;
        si.Uid = jsonObj["uid"].toInt();
        si.Host = jsonObj["host"].toString();
        si.Port = jsonObj["port"].toString();
        si.Token = jsonObj["token"].toString();

        m_uid = si.Uid;
        m_token = si.Token;
        qDebug() << "email is " << email << " uid is " << si.Uid <<" host is "
                 << si.Host << " Port is " << si.Port << " Token is " << si.Token;
        // 发送给TcpManager，让其调用Tcp的连接函数(TCP的发送可能在不同的线程里面，可能会不安全，需要将其通过队列的方式插入到TcpManager里面)
        // TcpManager就会在轮询的队列里面进行处理
        emit sig_connect_tcp(si);
    });
}

// 发送切换到重置密码界面的信号
void LoginDialog::slot_forget_pwd()
{
    qDebug() << "slot forget pwd";
    emit switchReset();
}

// 对登录回包后的信号进行处理，进行回调操作
void LoginDialog::slot_login_mod_finish(ReqId id, QString res, ErrorCodes err)
{
    if (err != ErrorCodes::SUCCESS){
        showTip(tr("网络请求错误"), false);
        return;
    }

    // 解析 JSON 字符串, res需转化为QByteArray
    QJsonDocument jsonDoc = QJsonDocument::fromJson(res.toUtf8());
    //json解析错误
    if (jsonDoc.isNull()){
        showTip(tr("json解析错误"), false);
        return;
    }

    //json解析错误
    if (!jsonDoc.isObject()){
        showTip(tr("json解析错误"), false);
        return;
    }


    //调用对应的逻辑,根据id回调。
    m_handlers[id](jsonDoc.object());

    return;
}

// 处理TcpManager发出的连接成功信号
void LoginDialog::slot_tcp_con_finish(bool b_success)
{
    if (b_success){
        showTip(tr("聊天服务连接成功，正在登录......"), true);
        QJsonObject jsonObj;
        jsonObj["uid"] = m_uid;
        jsonObj["token"] = m_token;

        QJsonDocument doc(jsonObj);
        QByteArray jsonData = doc.toJson(QJsonDocument::Indented);

        // 发送tcp请求给chat server
        emit TcpManager::getInstance()->sig_send_data(ReqId::ID_CHAT_LOGIN, jsonData);
    } else{
        showTip(tr("网络异常"), false);
        enableBtn(true);
    }
}

// 处理TcpManager发出的连接成功的信号
void LoginDialog::slot_login_failed(int err)
{
    QString result = QString("登录失败, err is %1").arg(err);
    showTip(result,false);
    enableBtn(true);
}

// 发送http登录请求
void LoginDialog::on_login_btn_clicked()
{
    qDebug() << "login btn clicked......";
    if (checkEmailValid() == false){
        return;
    }

    if (checkPwdValid() == false) {
        return ;
    }

    enableBtn(false);
    auto email = ui->email_edit->text();
    auto pwd = ui->pass_edit->text();
    // 发送http请求登录
    QJsonObject json_obj;
    json_obj["email"] = email;
    json_obj["passwd"] = xorString(pwd);
    qDebug() << "login passwd = " << json_obj["passwd"];
    HttpManager::getInstance()->PostHttpReq(QUrl(gate_url_prefix + "/user_login"),
                                        json_obj, ReqId::ID_LOGIN_USER, Modules::LOGINMOD);
}

